package utils

import (
	"bufio"
	"codejy/structdef"
	"fmt"
	"github.com/shirou/gopsutil/v3/net"
	"io"
	"os"
	"path"
	"strconv"
	"strings"
	"time"
)

func init() {
	go func() {
		for {
			time.Sleep(time.Hour * 1) //每隔一小时检查一次
			//判断是否会员到期
			if Member.ExpireTime != 0 && Member.ExpireTime < time.Now().Unix() {
				//判断Member.Month是否小于1,如果小于1就是按照天数计算
				if Member.Month < 1 {
					//获取小数点后面的数字
					monthStr := strings.Split(strconv.Itoa(Member.Month), ".")[1]
					fmt.Println(Member.Name + "会员用户你好,你购买的会员级别为" + strconv.Itoa(Member.Level) + ",购买的天数为" + monthStr + "的会员已到期," +
						"如需继续使用会员请从新购买,会员购买说明https://www.yuque.com/huanmin-4bkaa/odp0i8/bat8fre63z4gct8i")
				} else {
					fmt.Println(Member.Name + "会员用户你好,你购买的会员级别为" + strconv.Itoa(Member.Level) + ",购买的月数为" + strconv.Itoa(Member.Month) + "的会员已到期," +
						"如需继续使用会员请从新购买,会员购买说明https://www.yuque.com/huanmin-4bkaa/odp0i8/bat8fre63z4gct8i")
				}
				DeleteMemberCodeFile() //删除会员码文件
				os.Exit(1)
			}
			//判断到期时间小于3天,如果小于3天就提示用户续费
			if Member.ExpireTime != 0 && Member.ExpireTime < time.Now().Unix()+60*60*24*3 {
				//获取差几天
				days := (Member.ExpireTime - time.Now().Unix()) / 60 / 60 / 24
				fmt.Printf("你的会员还剩%d天到期,到期时间为%s,请及时续费,会员购买说明https://www.yuque.com/huanmin-4bkaa/odp0i8/bat8fre63z4gct8i\n", days, Member.ExpireTimeFormat)

			}

		}
	}()
}

// max+购买日期(时间戳)+期限月+会员等级+会员名称
// 秘钥
var SecretDey = "yiyuanhuanminabc"

// 初始向量
var Iv = []byte("qwertyuiopasdfgh")

// 记录代码执行行数(进行限速),而for if ,switch 无论内部干了啥都只会算做一次而已
var ChargeCodeLine int

// 会员级别
var Member struct {
	// 会员级别
	Level int
	//购买时间
	BuyTime int64
	// 会员到期时间
	ExpireTime int64
	//会员到时时间格式化
	ExpireTimeFormat string
	// 会员名称
	Name string
	//会员码
	Code string
	//购买月
	Month int
	//购买日
	Day int
	//mac地址
	Mac string
}

// 实现String()方法
func MemberString() {
	fmt.Printf("Mac:%s\n会员级别:%s\n会员到期时间:%s\n会员名称:%s\n会员码:%s\n购买(%d)月\n购买(%d)日\n",
		Member.Mac, RankConvert(Member.Level), Member.ExpireTimeFormat, Member.Name, Member.Code, Member.Month, Member.Day)
}

func init() {
	//初始化会员信息
	Member.Level = 0
	Member.ExpireTime = 0
	Member.ExpireTimeFormat = ""
	Member.Name = ""
	Member.Code = ""
	Member.Month = 0
	Member.Day = 0

}

// 添加会员
func AddMember() {
	fmt.Println("会员码认证中...")
	//解析会员码
	decryptCode := DecryptMember(Member.Code)
	//逗号分割
	memberArr := strings.Split(decryptCode, ",")
	var macConfirmation = false
	//获取mac
	mac := strings.ToLower(memberArr[0])
	//如果mac地址是all,则不验证mac地址
	if mac != "all" {
		//替换-为:
		mac = strings.Replace(mac, "-", ":", -1)
		// 获取本机的MAC地址
		interfaces, err := net.Interfaces()
		if err != nil {
			panic("Poor soul, here is what you got: " + err.Error())
		}
		for _, inter := range interfaces {
			localMac := inter.HardwareAddr //获取本机MAC地址
			if localMac == mac {
				macConfirmation = true
				break
			}
		}
	}

	if mac == "all" || macConfirmation {
		//mac
		Member.Mac = mac
		//获取购买时间
		Member.BuyTime, _ = strconv.ParseInt(memberArr[1], 10, 64)
		//获取期限月
		Member.Month, _ = strconv.Atoi(memberArr[2])
		//如果是0.x的会员就是按照天数计算
		if Member.Month < 1 {
			//获取到期时间
			//截取小数点后面的数字
			monthStr := strings.Split(memberArr[2], ".")[1]
			//获取小数点后面的数字
			month, _ := strconv.Atoi(monthStr)
			Member.Day = month
			Member.ExpireTime = Member.BuyTime + int64(month*24*60*60)
		} else {
			//获取到期时间
			Member.ExpireTime = Member.BuyTime + int64(Member.Month*30*24*60*60)
		}
		//时间格式化
		timeLayout := "2006-01-02 15:04:05"
		Member.ExpireTimeFormat = time.Unix(Member.ExpireTime, 0).Format(timeLayout)
		//会员级别
		Member.Level, _ = strconv.Atoi(memberArr[3])
		//会员名称
		Member.Name = memberArr[4]
		//将会员码写入到文件
		WriteMemberCodeFile()
		//会员码认证成功
		fmt.Println("会员码认证成功")
		//打印会员信息
		fmt.Println("会员信息如下:")
		MemberString()

	} else {
		fmt.Println("会员码mac地址不对" + mac + ",本机没有找到符合的,会员购买说明https://www.yuque.com/huanmin-4bkaa/odp0i8/bat8fre63z4gct8i")
		os.Exit(1)
	}

}

// 根据ChargeCodeLine进行限速
func LimitSpeed(threadStore *structdef.ThreadStore) {
	//排除核心代码
	if strings.HasPrefix(threadStore.Code.LineContent, "core") || strings.HasPrefix(threadStore.Code.LineContent, "tocore") {
		return
	}
	ChargeCodeLine++
	switch Member.Level {
	case 0: //免费会员
		if ChargeCodeLine > 500 {
			time.Sleep(time.Millisecond * 100)
		}
	case 1: //青铜会员
		if ChargeCodeLine > 5000 {
			time.Sleep(time.Millisecond * 50)
		}
	case 2: //白银会员
		if ChargeCodeLine > 20000 {
			time.Sleep(time.Microsecond * 800)
		}
	case 3: //黄金会员
		if ChargeCodeLine > 100000 {
			time.Sleep(time.Microsecond * 500)
		}
	case 4: //至尊会员,不限速
	}
}

// 解密
func DecryptMember(str string) string {
	defer func() {
		if err := recover(); err != nil {
			fmt.Println("会员码解密失败,会员购买说明https://www.yuque.com/huanmin-4bkaa/odp0i8/bat8fre63z4gct8i")
			DeleteMemberCodeFile()
			os.Exit(1)
		}
	}()
	result := CBCDecrypterStr(str, []byte(SecretDey), Iv)
	return result
}

// 去用户主目录下找codejy/membercode文件,读取之前认证的会员码
func FindMemberCodeFile() {
	//获取用户主目录
	home, err := os.UserHomeDir()
	if err != nil {
		panic(err)
	}
	join := path.Join(home, "codejy", "membercode")
	_, err = os.Stat(join)
	if err != nil {
		DebugLog(join+"没有找到会员码文件", func() {})
		return
	}
	//读取文件第一行
	file, err := os.Open(join)
	if err != nil {
		panic(err)
	}
	defer file.Close()
	reader := bufio.NewReader(file)
	line, _, err := reader.ReadLine()
	if err != io.EOF && err != nil {
		panic(err)
	}
	if len(line) > 0 {
		fmt.Println("检测到本机已经认证过会员码,会员码为:" + string(line))
	}
	//去除空格
	lineStr := strings.TrimSpace(string(line))
	Member.Code = lineStr
}

// 将会员码写入文件
func WriteMemberCodeFile() {

	//获取用户主目录
	home, err := os.UserHomeDir()
	if err != nil {
		panic(err)
	}
	join := path.Join(home, "codejy", "membercode")
	//创建文件夹
	err = os.MkdirAll(path.Join(home, "codejy"), os.ModePerm)
	if err != nil {
		panic(err)
	}
	//创建文件
	file, err := os.OpenFile(join, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0644)
	if err != nil {
		panic(err)
	}
	defer file.Close()
	//写入
	_, err = file.WriteString(Member.Code)
	if err != nil {
		panic(err)
	}
}

// 删除会员码文件
func DeleteMemberCodeFile() {
	//获取用户主目录
	home, err := os.UserHomeDir()
	if err != nil {
		panic(err)
	}
	join := path.Join(home, "codejy", "membercode")
	err = os.Remove(join)
	if err != nil {
		panic(err)
	}
}

// 生成会员码,字符串,max+购买日期(时间戳)+期限月+会员等级+会员名称
// 返回加密后的字符串
func GetMemberCode(mac string, month string, rank int, name string) string {
	var str string = mac
	//获取当前时间的时间戳
	nowUnix := time.Now().Unix()
	str += "," + strconv.FormatInt(nowUnix, 10)
	//添加月
	str += "," + month
	//添加等级
	str += "," + strconv.Itoa(rank)
	//添加名称
	str += "," + name
	//加密
	result := CBCEncrypterStr(str, []byte(SecretDey), Iv)
	return result
}

// 会员信息打印
func PrintMemberInfo() {
	//判断是否过期
	if Member.ExpireTime != 0 && Member.ExpireTime < time.Now().Unix() {
		fmt.Println("你的会员已经过期,如需继续使用会员请从新购买,会员购买说明https://www.yuque.com/huanmin-4bkaa/odp0i8/bat8fre63z4gct8i")
		DeleteMemberCodeFile() //删除会员码文件
		os.Exit(1)
	}
	switch Member.Level {
	case 1:
		printMember("青铜会员")
	case 2:
		printMember("白银会员")
	case 3:
		printMember("黄金会员")
	case 4:
		printMember("至尊会员")
	default:
		fmt.Println("易语言,免费版")
	}
}
func printMember(name string) {
	if Member.Day != 0 {
		fmt.Printf("尊敬的%s(%s)你好,欢迎使用易语言,你当前购买了%d日的会员,过期时间为%s \n", name, Member.Name, Member.Day, Member.ExpireTimeFormat)
	} else {
		fmt.Printf("尊敬的%s(%s)你好,欢迎使用易语言,你当前购买了%d月的会员,过期时间为%s \n", name, Member.Name, Member.Month, Member.ExpireTimeFormat)
	}
}

// 级别转换
func RankConvert(rank int) string {
	switch rank {
	case 1:
		return "青铜会员"
	case 2:
		return "白银会员"
	case 3:
		return "黄金会员"
	case 4:
		return "至尊会员"
	default:
		return "免费版"
	}
}
